package de.rs.espresso.problems;

import java.util.List;

import de.rs.espresso.algorithms.Expand;
import de.rs.espresso.algorithms.Irredundant;
import de.rs.espresso.algorithms.LastGasp;
import de.rs.espresso.algorithms.Reduce;
import de.rs.espresso.covers.DefaultCover;
import de.rs.espresso.interfaces.ICover;
import de.rs.espresso.interfaces.IGlobalInformation;
import de.rs.espresso.interfaces.IProblem;
import de.rs.espresso.interfaces.IResult;


/**
 * 
 * Internal Class representation of a parsed BLIF-File.
 * 
 * @author Jan
 *
 */
public class LogicalMinimizationProblem implements IProblem, IResult {
		
	
	private boolean solved = false;
	
	private static int idCounter = 0;
	
	private String identifier;
	
	private List<String> columnNameList;
	
	private ICover onSet;

	private ICover dcSet;
	
	private ICover offSet;

	private IGlobalInformation info;

	private boolean demo = false;

	public static int maxLoop = 0;
	
	public LogicalMinimizationProblem(List<String> columnNameList, ICover onSet, ICover dcSet, IGlobalInformation info) {
		
		this.columnNameList = columnNameList;
		
		this.onSet = onSet;
		
		this.dcSet = dcSet;
		
		if(this.dcSet==null) {
			this.dcSet = new DefaultCover(info);
		}
		
		this.info = info;
		
		identifier = "$$$problem_id_"+(++idCounter)+"$$$";
	}
	
	public static void resetIDGenerator() {
		idCounter = 0;
	}
	

	@Override
	public void solve() {
		
		int loop = 0;
		
		if(demo) {
			onSet.draw("BEFORE");
		}
		
		ICover onSet1 = new DefaultCover(info);
		
		for(ICover c : onSet.getSingleOutputCovers()) {
			onSet1.addAll(c);
		}
		onSet = onSet1;		

		offSet = onSet.getComplement(dcSet);
		
		
		onSet = new Expand(info).compute(onSet, offSet, dcSet);		
		
		onSet = new Irredundant(info).compute(onSet, offSet, dcSet);
		
		//ESSENTIAL_PRIMES
		
		ICover clonedOnSet1;
		ICover clonedOnSet2;
		
		
		do {
			
			clonedOnSet1 = onSet.clone();
			
			do {
				loop++;	
				
				clonedOnSet2 = onSet.clone();
				
				onSet = new Reduce(info).compute(onSet, offSet, dcSet);
				onSet = new Expand(info).compute(onSet, offSet, dcSet);
				onSet = new Irredundant(info).compute(onSet, offSet, dcSet);

				
			}while(clonedOnSet2.size()>onSet.size());
		
			onSet = new LastGasp(info).compute(onSet,offSet,dcSet);
			
		}while(clonedOnSet1.compareCost(onSet));
		
		onSet = clonedOnSet1;
		
		//onSet = new Expand(info).compute(onSet, offSet, dcSet);
		
		solved = true;

		
		

		if(demo) {
			onSet.draw("AFTER");
		}
		
		if(maxLoop<loop) maxLoop=loop;

	}

	public String getIdentifier() {
		return identifier;
	}


	@Override
	public IResult getResult() {
		return solved?this:null;
	}


	@Override
	public Object getObject() {
		return this;
	}


	@Override
	public void demo() {
		demo = true;
		
	}
	
	public ICover getCover() {
		return onSet;
	}
	
	public List<String> getNames() {
		return columnNameList;
	}
	




}
